home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcl / sptmbr16.lha / walk.lisp < prev    next >
Text File  |  1992-12-21  |  74KB  |  2,184 lines

  1. ;;;-*- Mode:LISP; Package:(WALKER LISP 1000); Base:10; Syntax:Common-lisp -*-
  2. ;;;
  3. ;;; *************************************************************************
  4. ;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
  5. ;;; All rights reserved.
  6. ;;;
  7. ;;; Use and copying of this software and preparation of derivative works
  8. ;;; based upon this software are permitted.  Any distribution of this
  9. ;;; software or derivative works must comply with all applicable United
  10. ;;; States export control laws.
  11. ;;; 
  12. ;;; This software is made available AS IS, and Xerox Corporation makes no
  13. ;;; warranty about the software, its performance or its conformity to any
  14. ;;; specification.
  15. ;;; 
  16. ;;; Any person obtaining a copy of this software is requested to send their
  17. ;;; name and post office or electronic mail address to:
  18. ;;;   CommonLoops Coordinator
  19. ;;;   Xerox PARC
  20. ;;;   3333 Coyote Hill Rd.
  21. ;;;   Palo Alto, CA 94304
  22. ;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
  23. ;;;
  24. ;;; Suggestions, comments and requests for improvements are also welcome.
  25. ;;; *************************************************************************
  26. ;;; 
  27. ;;; A simple code walker, based IN PART on: (roll the credits)
  28. ;;;   Larry Masinter's Masterscope
  29. ;;;   Moon's Common Lisp code walker
  30. ;;;   Gary Drescher's code walker
  31. ;;;   Larry Masinter's simple code walker
  32. ;;;   .
  33. ;;;   .
  34. ;;;   boy, thats fair (I hope).
  35. ;;;
  36. ;;; For now at least, this code walker really only does what PCL needs it to
  37. ;;; do.  Maybe it will grow up someday.
  38. ;;;
  39.  
  40. ;;;
  41. ;;; This code walker used to be completely portable.  Now it is just "Real
  42. ;;; easy to port".  This change had to happen because the hack that made it
  43. ;;; completely portable kept breaking in different releases of different
  44. ;;; Common Lisps, and in addition it never worked entirely anyways.  So,
  45. ;;; its now easy to port.  To port this walker, all you have to write is one
  46. ;;; simple macro and two simple functions.  These macros and functions are
  47. ;;; used by the walker to manipluate the macroexpansion environments of
  48. ;;; the Common Lisp it is running in.
  49. ;;;
  50. ;;; The code which implements the macroexpansion environment manipulation
  51. ;;; mechanisms is in the first part of the file, the real walker follows it.
  52. ;;; 
  53.  
  54. (in-package :walker)
  55.  
  56. ;;;
  57. ;;; The user entry points are walk-form and nested-walked-form.  In addition,
  58. ;;; it is legal for user code to call the variable information functions:
  59. ;;; variable-lexical-p, variable-special-p and variable-class.  Some users
  60. ;;; will need to call define-walker-template, they will have to figure that
  61. ;;; out for themselves.
  62. ;;; 
  63. (export '(define-walker-template
  64.       walk-form
  65.       walk-form-expand-macros-p
  66.       nested-walk-form
  67.       variable-lexical-p
  68.       variable-special-p
  69.       variable-globally-special-p
  70.       *variable-declarations*
  71.       variable-declaration
  72.       macroexpand-all
  73.       ))
  74.  
  75.  
  76.  
  77. ;;;
  78. ;;; On the following pages are implementations of the implementation specific
  79. ;;; environment hacking functions for each of the implementations this walker
  80. ;;; has been ported to.  If you add a new one, so this walker can run in a new
  81. ;;; implementation of Common Lisp, please send the changes back to us so that
  82. ;;; others can also use this walker in that implementation of Common Lisp.
  83. ;;;
  84. ;;; This code just hacks 'macroexpansion environments'.  That is, it is only
  85. ;;; concerned with the function binding of symbols in the environment.  The
  86. ;;; walker needs to be able to tell if the symbol names a lexical macro or
  87. ;;; function, and it needs to be able to build environments which contain
  88. ;;; lexical macro or function bindings.  It must be able, when walking a
  89. ;;; macrolet, flet or labels form to construct an environment which reflects
  90. ;;; the bindings created by that form.  Note that the environment created
  91. ;;; does NOT have to be sufficient to evaluate the body, merely to walk its
  92. ;;; body.  This means that definitions do not have to be supplied for lexical
  93. ;;; functions, only the fact that that function is bound is important.  For
  94. ;;; macros, the macroexpansion function must be supplied.
  95. ;;;
  96. ;;; This code is organized in a way that lets it work in implementations that
  97. ;;; stack cons their environments.  That is reflected in the fact that the
  98. ;;; only operation that lets a user build a new environment is a with-body
  99. ;;; macro which executes its body with the specified symbol bound to the new
  100. ;;; environment.  No code in this walker or in PCL will hold a pointer to
  101. ;;; these environments after the body returns.  Other user code is free to do
  102. ;;; so in implementations where it works, but that code is not considered
  103. ;;; portable.
  104. ;;;
  105. ;;; There are 3 environment hacking tools.  One macro which is used for
  106. ;;; creating new environments, and two functions which are used to access the
  107. ;;; bindings of existing environments.
  108. ;;;
  109. ;;; WITH-AUGMENTED-ENVIRONMENT
  110. ;;;
  111. ;;; ENVIRONMENT-FUNCTION
  112. ;;;
  113. ;;; ENVIRONMENT-MACRO
  114. ;;; 
  115.  
  116. (defun unbound-lexical-function (&rest args)
  117.   (declare (ignore args))
  118.   (error "The evaluator was called to evaluate a form in a macroexpansion~%~
  119.           environment constructed by the PCL portable code walker.  These~%~
  120.           environments are only useful for macroexpansion, they cannot be~%~
  121.           used for evaluation.~%~
  122.           This error should never occur when using PCL.~%~
  123.           This most likely source of this error is a program which tries to~%~
  124.           to use the PCL portable code walker to build its own evaluator."))
  125.  
  126.  
  127. ;;;
  128. ;;; In Coral Common Lisp, the macroexpansion environment is just a list
  129. ;;; of environment entries.  The cadr of each element specifies the type
  130. ;;; of the element.  The only types that interest us are CCL::MACRO and
  131. ;;; FUNCTION.  In these cases the element is interpreted as follows.
  132. ;;;
  133. ;;;   (<function-name> CCL::MACRO . macroexpansion-function)
  134. ;;;   
  135. ;;;   (<function-name> FUNCTION . <fn>)
  136. ;;;   
  137. ;;;   When in the compiler, <fn> is a gensym which will be
  138. ;;;   a variable which bound at run-time to the function.
  139. ;;;   When in the interpreter, <fn> is the actual function.
  140. ;;;   
  141. ;;;
  142. #+:Coral
  143. (progn
  144.  
  145. (defmacro with-augmented-environment
  146.       ((new-env old-env &key functions macros) &body body)
  147.   `(let ((,new-env (with-augmented-environment-internal ,old-env
  148.                             ,functions
  149.                             ,macros)))
  150.      ,@body))
  151.  
  152. (defun with-augmented-environment-internal (env functions macros)
  153.   (dolist (f functions)
  154.     (push (list* f 'function (gensym)) env))
  155.   (dolist (m macros)
  156.     (push (list* (car m) 'ccl::macro (cadr m)) env))
  157.   env)
  158.  
  159. (defun environment-function (env fn)
  160.   (let ((entry (assoc fn env :test #'equal)))
  161.     (and entry
  162.      (eq (cadr entry) 'function)
  163.      (cddr entry))))
  164.  
  165. (defun environment-macro (env macro)
  166.   (let ((entry (assoc macro env :test #'equal)))
  167.     (and entry
  168.      (eq (cadr entry) 'ccl::macro)
  169.      (cddr entry))))
  170.  
  171. );#+:Coral
  172.  
  173.  
  174. ;;;
  175. ;;; Franz Common Lisp is a lot like Coral Lisp.  The macroexpansion
  176. ;;; environment is just a list of entries.  The cadr of each element
  177. ;;; specifies the type of the element.  The types that interest us
  178. ;;; are FUNCTION, EXCL::MACRO, and COMPILER::FUNCTION-VALUE.  These
  179. ;;; are interpreted as follows:
  180. ;;;
  181. ;;;   (<function-name> FUNCTION . <a lexical closure>)
  182. ;;;
  183. ;;;      This happens in the interpreter with lexically
  184. ;;;      bound functions.
  185. ;;;
  186. ;;;   (<function-name> COMPILER::FUNCTION-VALUE . <gensym>)
  187. ;;;
  188. ;;;      This happens in the compiler.  The gensym represents
  189. ;;;      a variable which will be bound at run time to the
  190. ;;;      function object.
  191. ;;;
  192. ;;;   (<function-name> EXCL::MACRO . <a lambda>)
  193. ;;;
  194. ;;;      In both interpreter and compiler, this is the
  195. ;;;      representation used for macro definitions.
  196. ;;;   
  197. ;;;
  198. #+:ExCL
  199. (progn
  200.  
  201. (defmacro with-augmented-environment
  202.       ((new-env old-env &key functions macros) &body body)
  203.   `(let ((,new-env (with-augmented-environment-internal ,old-env
  204.                             ,functions
  205.                             ,macros)))
  206.      ,@body))
  207.  
  208. (defun with-augmented-environment-internal (env functions macros)
  209.   (let (#+allegro-v4.1 (env-tail (cdr env)) #+allegro-v4.1 (env (car env)))
  210.     (dolist (f functions)
  211.       (push (list* f 'function #'unbound-lexical-function) env))
  212.     (dolist (m macros)
  213.       (push (list* (car m) 'excl::macro (cadr m)) env))
  214.     #-allegro-v4.1 env #+allegro-v4.1 (cons env env-tail)))
  215.  
  216. (defun environment-function (env fn)
  217.   (let* (#+allegro-v4.1 (env (car env))
  218.      (entry (assoc fn env :test #'equal)))
  219.     (and entry
  220.      (or (eq (cadr entry) 'function)
  221.          (eq (cadr entry) 'compiler::function-value))
  222.      (cddr entry))))
  223.  
  224. (defun environment-macro (env macro)
  225.   (let* (#+allegro-v4.1 (env (car env))
  226.      (entry (assoc macro env :test #'equal)))
  227.     (and entry
  228.      (eq (cadr entry) 'excl::macro)
  229.      (cddr entry))))
  230.  
  231. );#+:ExCL
  232.  
  233.  
  234. #+Lucid
  235. (progn
  236.   
  237. (proclaim '(inline
  238.         %alphalex-p
  239.         add-contour-to-env-shape
  240.         make-function-variable
  241.         make-sfc-contour
  242.         sfc-contour-type
  243.         sfc-contour-elements
  244.         add-sfc-contour
  245.         add-function-contour
  246.         add-macrolet-contour
  247.         find-variable-in-contour
  248.         find-alist-element-in-contour
  249.         find-macrolet-in-contour))
  250.  
  251. (defun %alphalex-p (object)
  252.   #-Prime
  253.   (eq (cadddr (cddddr object)) 'lucid::%alphalex)
  254.   #+Prime
  255.   (eq (caddr (cddddr object)) 'lucid::%alphalex))
  256.  
  257. #+Prime 
  258. (defun lucid::augment-lexenv-fvars-dummy (lexical vars)
  259.   (lucid::augment-lexenv-fvars-aux lexical vars '() '() 'flet '()))
  260.  
  261. (defconstant function-contour 1)
  262. (defconstant macrolet-contour 5)
  263.  
  264. (defstruct lucid::contour
  265.   type
  266.   elements)
  267.  
  268. (defun add-contour-to-env-shape (contour-type elements env-shape)
  269.   (cons (make-contour :type contour-type
  270.               :elements elements)
  271.     env-shape))
  272.  
  273. (defstruct (variable (:constructor make-variable (name source-type)))
  274.   name
  275.   (identifier nil)
  276.   source-type)
  277.  
  278. (defconstant function-sfc-contour 1)
  279. (defconstant macrolet-sfc-contour 8)
  280. (defconstant function-variable-type 1)
  281.  
  282. (defun make-function-variable (name)
  283.   (make-variable name function-variable-type))
  284.  
  285. (defun make-sfc-contour (type elements)
  286.   (cons type elements))
  287.  
  288. (defun sfc-contour-type (sfc-contour)
  289.   (car sfc-contour))
  290.  
  291. (defun sfc-contour-elements (sfc-contour)
  292.   (cdr sfc-contour))
  293.  
  294. (defun add-sfc-contour (element-list environment type)
  295.   (cons (make-sfc-contour type element-list) environment))
  296.  
  297. (defun add-function-contour (variable-list environment)
  298.   (add-sfc-contour variable-list environment function-sfc-contour))
  299.  
  300. (defun add-macrolet-contour (alist environment)
  301.   (add-sfc-contour alist environment macrolet-sfc-contour))
  302.  
  303. (defun find-variable-in-contour (name contour)
  304.   (dolist (element (sfc-contour-elements contour) nil)
  305.     (when (eq (variable-name element) name)
  306.       (return element))))
  307.  
  308. (defun find-alist-element-in-contour (name contour)
  309.   (cdr (assoc name (sfc-contour-elements contour))))
  310.  
  311. (defun find-macrolet-in-contour (name contour)
  312.   (find-alist-element-in-contour name contour))
  313.  
  314. (defmacro do-sfc-contours ((contour-var environment &optional result)
  315.                &body body)
  316.   `(dolist (,contour-var ,environment ,result) ,@body))
  317.  
  318.  
  319. (defmacro with-augmented-environment
  320.       ((new-env old-env &key functions macros) &body body)     
  321.   `(let* ((,new-env (with-augmented-environment-internal ,old-env
  322.                              ,functions
  323.                              ,macros)))
  324.      ,@body))
  325.  
  326. ;;;
  327. ;;; with-augmented-environment-internal is where the real work of augmenting
  328. ;;; the environment happens.
  329. ;;; 
  330. (defun with-augmented-environment-internal (env functions macros)
  331.   (let ((function-names (mapcar #'first functions))
  332.     (macro-names (mapcar #'first macros))
  333.     (macro-functions (mapcar #'second macros)))
  334.     (cond ((or (null env)
  335.            (contour-p (first env)))
  336.        (when function-names
  337.          (setq env (add-contour-to-env-shape function-contour
  338.                          function-names
  339.                          env)))
  340.        (when macro-names
  341.          (setq env (add-contour-to-env-shape macrolet-contour
  342.                          (pairlis macro-names
  343.                               macro-functions)
  344.                          env))))
  345.       ((%alphalex-p env)
  346.        (when function-names
  347.          (setq env (lucid::augment-lexenv-fvars-dummy env function-names)))
  348.        (when macro-names
  349.          (setq env (lucid::augment-lexenv-mvars env
  350.                             macro-names
  351.                             macro-functions))))
  352.       (t
  353.        (when function-names
  354.          (setq env (add-function-contour
  355.              (mapcar #'make-function-variable function-names)
  356.              env)))
  357.        (when macro-names
  358.          (setq env (add-macrolet-contour
  359.              (pairlis macro-names macro-functions)
  360.              env)))))
  361.     env))
  362.      
  363.  
  364. (defun environment-function (env fn)
  365.   (cond ((null env) nil)
  366.     ((contour-p (first env))
  367.      (if (lucid::find-lexical-function fn env)
  368.          t
  369.          nil))
  370.     ((%alphalex-p env)
  371.      (if (lucid::lexenv-fvar fn env)
  372.          t
  373.          nil))
  374.     (t (do-sfc-contours (contour env nil)
  375.          (let ((type (sfc-contour-type contour)))
  376.            (cond ((eql type function-sfc-contour)
  377.               (when (find-variable-in-contour fn contour)
  378.             (return t)))
  379.              ((eql type macrolet-sfc-contour)
  380.               (when (find-macrolet-in-contour fn contour)
  381.             (return nil)))))))))
  382.               
  383. (defun environment-macro (env macro)
  384.   (cond ((null env) nil)
  385.     ((contour-p (first env))
  386.      (lucid::find-lexical-macro macro env))
  387.     ((%alphalex-p env)
  388.      (lucid::lexenv-mvar macro env))
  389.     (t (do-sfc-contours (contour env nil)
  390.          (let ((type (sfc-contour-type contour)))
  391.            (cond ((eql type function-sfc-contour)
  392.               (when (find-variable-in-contour macro contour)
  393.             (return nil)))
  394.              ((eql type macrolet-sfc-contour)
  395.               (let ((fn (find-macrolet-in-contour macro contour)))
  396.             (when fn
  397.               (return fn))))))))))
  398.   
  399.  
  400. );#+Lucid
  401.  
  402.  
  403.  
  404. ;;;
  405. ;;; On the 3600, the documentation for how the environments are represented
  406. ;;; is in sys:sys;eval.lisp.  That total information is not repeated here.
  407. ;;; The important points are that:
  408. ;;;    si:env-variables returns a list of which each element is:
  409. ;;;
  410. ;;;        (symbol value)
  411. ;;;         or (symbol . locative)
  412. ;;;
  413. ;;;    The first form is for lexical variables, the second for
  414. ;;;    special and instance variables.  In either case CADR of
  415. ;;;    the entry is the value and SETF of CADR is used to change
  416. ;;;    the value.  Variables are looked up with ASSQ.
  417. ;;;
  418. ;;;    si:env-functions returns a list of which each element is:
  419. ;;;     
  420. ;;;        (symbol definition)
  421. ;;;
  422. ;;;    where definition is anything that could go in a function cell.
  423. ;;;    This is used for both local functions and local macros.
  424. ;;;
  425. ;;; The 3600 stack conses its environments (at least in the interpreter).
  426. ;;; This means that code written using this walker and running on the 3600
  427. ;;; must not hold on to the environment after the walk-function returns.
  428. ;;; No code in this walker or in PCL does that.
  429. ;;;
  430. #+Genera
  431. (progn
  432.  
  433. (defmacro with-augmented-environment
  434.       ((new-env old-env &key functions macros) &body body)
  435.   (let ((funs (make-symbol "FNS"))
  436.     (macs (make-symbol "MACROS"))
  437.     (new  (make-symbol "NEW")))
  438.     `(let ((,funs ,functions)
  439.        (,macs ,macros)
  440.        (,new ()))
  441.        (dolist (f ,funs)
  442.      (push `(,(car f) ,#'unbound-lexical-function) ,new))
  443.        (dolist (m ,macs)
  444.      (push `(,(car m) (special ,(cadr m))) ,new))
  445.        (let* ((.old-env. ,old-env)
  446.           (.old-vars. (pop .old-env.))
  447.           (.old-funs. (pop .old-env.))
  448.           (.old-blks. (pop .old-env.))
  449.           (.old-tags. (pop .old-env.))
  450.           (.old-dcls. (pop .old-env.)))
  451.      (si:with-interpreter-environment (,new-env
  452.                        .old-env.
  453.                        .old-vars.
  454.                        (append ,new .old-funs.)
  455.                        .old-blks.
  456.                        .old-tags.
  457.                        .old-dcls.)
  458.        ,@body)))))
  459.   
  460.  
  461. (defun environment-function (env fn)
  462.   (if (null env)
  463.       (values nil nil)
  464.       (let ((entry (assoc fn (si:env-functions env) :test #'equal)))
  465.     (if (and entry
  466.          (or (not (listp (cadr entry)))
  467.              (not (eq (caadr entry) 'special))))
  468.         (values (cadr entry) t)
  469.         (environment-function (si:env-parent env) fn)))))
  470.  
  471. (defun environment-macro (env macro)
  472.   (if (null env)
  473.       (values nil nil)
  474.       (let ((entry (assoc macro (si:env-functions env) :test #'equal)))
  475.     (if (and entry
  476.          (listp (cadr entry))
  477.          (eq (caadr entry) 'special))
  478.         (values (cadadr entry) t)
  479.         (environment-macro (si:env-parent env) macro)))))
  480.  
  481. );#+Genera
  482.  
  483. #+Cloe-Runtime
  484. (progn
  485.  
  486. (defmacro with-augmented-environment
  487.       ((new-env old-env &key functions macros) &body body)
  488.   `(let ((,new-env (with-augmented-environment-internal ,old-env ,functions ,macros)))
  489.      ,@body))
  490.  
  491. (defun with-augmented-environment-internal (env functions macros)
  492.   functions
  493.   (dolist (m macros)
  494.     (setf env `(,(first m) (compiler::macro . ,(second m)) ,@env)))
  495.   env)
  496.  
  497. (defun environment-function (env fn)
  498.   nil)
  499.  
  500. (defun environment-macro (env macro)
  501.   (let ((entry (getf env macro)))
  502.     (if (and (consp entry)
  503.          (eq (car entry) 'compiler::macro))
  504.     (values (cdr entry) t)
  505.     (values nil nil))))
  506.  
  507. );#+Cloe-Runtime
  508.  
  509.  
  510. ;;;
  511. ;;; In Xerox Lisp, the compiler and interpreter use different structures for
  512. ;;; the environment.  This doesn't cause a serious problem, the parts of the
  513. ;;; environments we are concerned with are fairly similar.
  514. ;;; 
  515. #+:Xerox
  516. (progn
  517.  
  518. (defmacro with-augmented-environment
  519.       ((new-env old-env &key functions macros) &body body)     
  520.   `(let* ((,new-env (with-augmented-environment-internal ,old-env
  521.                              ,functions
  522.                              ,macros)))
  523.      ,@body))
  524.  
  525. ;;;
  526. ;;; with-augmented-environment-internal is where the real work of augmenting
  527. ;;; the environment happens.  Before it gets there, env had better not be NIL
  528. ;;; anymore because we have to know what kind of environment we are supposed
  529. ;;; to be building up.  This is probably never a real concern in practice.
  530. ;;; It better not be because we don't do anything about it.
  531. ;;; 
  532. (defun with-augmented-environment-internal (env functions macros)
  533.   (cond
  534.      ((compiler::env-p env)
  535.     (dolist (f functions)
  536.        (setq env (compiler::copy-env-with-function
  537.                env f :function)))
  538.     (dolist (m macros)
  539.        (setq env (compiler::copy-env-with-function
  540.            env (car m) :macro (cadr m)))))
  541.      (t (setq env (if (il:environment-p env)
  542.             (il:\\copy-environment env)
  543.             (il:\\make-environment)))
  544.     ;; The functions field of the environment is a plist of function names
  545.     ;; and conses like (:function . fn) or (:macro . expansion-fn).
  546.     ;; Note that we can't smash existing entries in this plist since these
  547.     ;; are likely shared with older environments.
  548.     (dolist (f functions)
  549.       (setf (il:environment-functions env)
  550.         (list* f (cons :function #'unbound-lexical-function)
  551.                (il:environment-functions env))))
  552.     (dolist (m macros)
  553.       (setf (il:environment-functions env)
  554.         (list* (car m) (cons :macro (cadr m))
  555.                (il:environment-functions env))))))
  556.   env)
  557.  
  558. (defun environment-function (env fn)
  559.   (cond ((compiler::env-p env) (eq (compiler:env-fboundp env fn) :function))
  560.     ((il:environment-p env) (eq (getf (il:environment-functions env) fn)
  561.                     :function))
  562.     (t nil)))
  563.  
  564. (defun environment-macro (env macro) 
  565.   (cond ((compiler::env-p env)
  566.      (multiple-value-bind (type def)
  567.          (compiler:env-fboundp env macro)
  568.        (when (eq type :macro) def)))
  569.     ((il:environment-p env)
  570.      (xcl:destructuring-bind (type . def)
  571.          (getf (il:environment-functions env) macro)
  572.        (when (eq type :macro) def)))
  573.     (t nil)))
  574.  
  575. );#+:Xerox
  576.  
  577.  
  578. ;;;
  579. ;;; In IBUKI Common Lisp, the macroexpansion environment is a three element
  580. ;;; list.  The second element describes lexical functions and macros.  The 
  581. ;;; function entries in this list have the form 
  582. ;;;     (<name> . (FUNCTION . (<function-value> . nil))
  583. ;;; The macro entries have the form 
  584. ;;;     (<name> . (MACRO . (<macro-value> . nil)).
  585. ;;;
  586. ;;;
  587. #+(or KCL IBCL)
  588. (progn
  589.  
  590. (defmacro with-augmented-environment
  591.       ((new-env old-env &key functions macros) &body body)
  592.       `(let ((,new-env (with-augmented-environment-internal ,old-env
  593.                                 ,functions
  594.                                 ,macros)))
  595.          ,@body))
  596.  
  597. (defun with-augmented-environment-internal (env functions macros)
  598.   (let ((first (first env))
  599.     (lexicals (second env))
  600.     (third (third env)))
  601.     (dolist (f functions)
  602.       (push `(,(car f) .  (function  . (,#'unbound-lexical-function . nil)))
  603.         lexicals))
  604.     (dolist (m macros)
  605.       (push `(,(car m)  .  (macro . ( ,(cadr m) . nil))) 
  606.         lexicals))
  607.     (list first lexicals third)))
  608.  
  609. (defun environment-function (env fn)
  610.   (when env
  611.     (let ((entry (assoc fn (second env))))
  612.       (and entry
  613.            (eq (cadr entry) 'function)
  614.            (caddr entry)))))
  615.  
  616. (defun environment-macro (env macro)
  617.   (when env
  618.     (let ((entry (assoc macro (second env))))
  619.       (and entry
  620.            (eq (cadr entry) 'macro)
  621.            (caddr entry)))))
  622. );#+(or KCL IBCL)
  623.  
  624.  
  625. ;;;   --- TI Explorer --
  626.  
  627. ;;; An environment is a two element list, whose car we can ignore and
  628. ;;; whose cadr is list of the local-definitions-frames. Each
  629. ;;; local-definitions-frame holds either macros or functions, but not
  630. ;;; both.  Each frame is a plist of <name> <def> <name> <def> ...  where
  631. ;;; <name> is a locative to the function cell of the symbol that names
  632. ;;; the function or macro, and <def> is the new def or NIL if this is function
  633. ;;; redefinition or (cons 'ticl:macro <macro-expansion-function>) if this is a macro
  634. ;;; redefinition.
  635. ;;;
  636. ;;; Here's an example.  For the form:
  637. ;;; (defun foo ()
  638. ;;;   (macrolet ((bar (a b) (list a b))
  639. ;;;             (bar2 (a b) (list a b)))
  640. ;;;     (flet ((some-local-fn (c d) (print (list c d)))
  641. ;;;           (another (c d) (print (list c d))))
  642. ;;;       (bar (some-local-fn 1 2) 3))))
  643.  
  644. ;;; the environment arg to macroexpand-1 when called on
  645. ;;; (bar (some-local-fn 1 2) 3)
  646. ;;;is 
  647. ;;;(NIL ((#<DTP-LOCATIVE 4710602> NIL
  648. ;;;       #<DTP-LOCATIVE 4710671> NIL)
  649. ;;;      (#<DTP-LOCATIVE 7346562>
  650. ;;;       (TICL:MACRO TICL:NAMED-LAMBDA (BAR (:DESCRIPTIVE-ARGLIST (A B)))
  651. ;;;           (SYS::*MACROARG* &OPTIONAL SYS::*MACROENVIRONMENT*)
  652. ;;;           (BLOCK BAR ....))
  653. ;;;       #<DTP-LOCATIVE 4710664>
  654. ;;;       (TICL:MACRO TICL:NAMED-LAMBDA (BAR2 (:DESCRIPTIVE-ARGLIST (A B)))
  655. ;;;           (SYS::*MACROARG* &OPTIONAL SYS::*MACROENVIRONMENT*)
  656. ;;;           (BLOCK BAR2 ....))))
  657. #+TI
  658. (progn 
  659.  
  660. ;;; from sys:site;macros.lisp
  661. (eval-when (compile load eval)
  662.   
  663. (DEFMACRO MACRO-DEF? (thing)
  664.   `(AND (CONSP ,thing) (EQ (CAR ,thing) 'TICL::MACRO)))
  665.  
  666. ;; the following macro generates code to check the 'local' environment
  667. ;; for a macro definition for THE SYMBOL <name>. Such a definition would
  668. ;; be set up only by a MACROLET. If a macro definition for <name> is
  669. ;; found, its expander function is returned.
  670.  
  671. (DEFMACRO FIND-LOCAL-DEFINITION (name local-function-environment)
  672.   `(IF ,local-function-environment
  673.        (LET ((vcell (ticl::LOCF (SYMBOL-FUNCTION ,name))))
  674.      (DOLIST (frame  ,local-function-environment)
  675.        ;; <value> is nil or a locative
  676.        (LET ((value (sys::GET-LOCATION-OR-NIL (ticl::LOCF frame)
  677.                           vcell))) 
  678.          (When value (RETURN (CAR value))))))
  679.        nil)))
  680.  
  681.  
  682. ;;;Edited by Reed Hastings         13 Jan 88  16:29
  683. (defun environment-macro (env macro)
  684.   "returns what macro-function would, ie. the expansion function"
  685.   ;;some code picked off macroexpand-1
  686.   (let* ((local-definitions (cadr env))
  687.      (local-def (find-local-definition macro local-definitions)))
  688.     (if (macro-def? local-def)
  689.     (cdr local-def))))
  690.  
  691. ;;;Edited by Reed Hastings         13 Jan 88  16:29
  692. ;;;Edited by Reed Hastings         7 Mar 88  19:07
  693. (defun environment-function (env fn)
  694.   (let* ((local-definitions (cadr env)))
  695.     (dolist (frame local-definitions)
  696.       (let ((val (getf frame
  697.                (ticl::locf (symbol-function fn))
  698.                :not-found-marker)))
  699.     (cond ((eq val :not-found-marker))
  700.           ((functionp val) (return t))
  701.           ((and (listp val)
  702.             (eq (car val) 'ticl::macro))
  703.            (return nil))
  704.           (t
  705.            (error "we are confused")))))))
  706.          
  707.  
  708. ;;;Edited by Reed Hastings         13 Jan 88  16:29
  709. ;;;Edited by Reed Hastings         7 Mar 88  19:07
  710. (defun with-augmented-environment-internal (env functions macros)
  711.   (let ((local-definitions (cadr env))
  712.     (new-local-fns-frame
  713.       (mapcan #'(lambda (fn)
  714.               (list (ticl:locf (symbol-function (car fn)))
  715.                 #'unbound-lexical-function))
  716.           functions))
  717.      (new-local-macros-frame
  718.        (mapcan #'(lambda (m)
  719.                (list (ticl:locf (symbol-function (car m))) (cons 'ticl::macro (cadr m))))
  720.            macros)))
  721.     (when new-local-fns-frame 
  722.       (push new-local-fns-frame local-definitions))
  723.     (when new-local-macros-frame
  724.       (push new-local-macros-frame local-definitions))   
  725.     `(,(car env) ,local-definitions)))
  726.  
  727.  
  728. ;;;Edited by Reed Hastings         7 Mar 88  19:07
  729. (defmacro with-augmented-environment
  730.       ((new-env old-env &key functions macros) &body body)
  731.   `(let ((,new-env (with-augmented-environment-internal ,old-env
  732.                             ,functions
  733.                             ,macros)))
  734.      ,@body))
  735.  
  736. );#+TI
  737.  
  738.  
  739. #+(and dec vax common)
  740. (progn
  741.  
  742. (defmacro with-augmented-environment
  743.       ((new-env old-env &key functions macros) &body body)
  744.   `(let ((,new-env (with-augmented-environment-internal ,old-env
  745.                             ,functions
  746.                             ,macros)))
  747.      ,@body))
  748.  
  749. (defun with-augmented-environment-internal (env functions macros)
  750.   #'(lambda (op &optional (arg nil arg-p))
  751.       (cond ((eq op :macro-function) 
  752.          (unless arg-p (error "Invalid environment use."))
  753.          (lookup-macro-function arg env functions macros))
  754.             (arg-p
  755.          (error "Invalid environment operation: ~S ~S" op arg))
  756.             (t
  757.          (lookup-macro-function op env functions macros)))))
  758.  
  759. (defun lookup-macro-function (name env fns macros)
  760.   (let ((m (assoc name macros)))
  761.     (cond (m                (cadr m))
  762.           ((assoc name fns) :function)
  763.           (env              (funcall env name))
  764.           (t                nil))))
  765.  
  766. (defun environment-macro (env macro)
  767.   (let ((m (and env (funcall env macro))))
  768.     (and (not (eq m :function)) 
  769.          m)))
  770.  
  771. ;;; Nobody calls environment-function.  What would it return, anyway?
  772. );#+(and dec vax common)
  773.  
  774.  
  775. ;;;
  776. ;;; In Golden Common Lisp, the macroexpansion environment is just a list
  777. ;;; of environment entries.  Unless the car of the list is :compiler-menv 
  778. ;;; it is an interpreted environment.  The cadr of each element specifies 
  779. ;;; the type of the element.  The only types that interest us are GCL:MACRO
  780. ;;; and FUNCTION.  In these cases the element is interpreted as follows.
  781. ;;;
  782. ;;; Compiled:
  783. ;;;   (<function-name> <gensym> macroexpansion-function)
  784. ;;;   (<function-name> <fn>)
  785. ;;;   
  786. ;;; Interpreted:
  787. ;;;   (<function-name> GCL:MACRO macroexpansion-function)
  788. ;;;   (<function-name> <fn>)
  789. ;;;   
  790. ;;;   When in the compiler, <fn> is a gensym which will be
  791. ;;;   a variable which bound at run-time to the function.
  792. ;;;   When in the interpreter, <fn> is the actual function.
  793. ;;;   
  794. ;;;
  795. #+gclisp
  796. (progn
  797.  
  798. (defmacro with-augmented-environment
  799.       ((new-env old-env &key functions macros) &body body)
  800.   `(let ((,new-env (with-augmented-environment-internal ,old-env
  801.                             ,functions
  802.                             ,macros)))
  803.      ,@body))
  804.  
  805. (defun with-augmented-environment-internal (env functions macros)
  806.   (let ((new-entries nil))
  807.     (dolist (f functions)
  808.       (push (cons (car f) nil) new-entries))
  809.     (dolist (m macros)
  810.       (push (cons (car m)
  811.           (if (eq :compiler-menv (car env))
  812.               (if (eq (caadr m) 'lisp::lambda)
  813.               `(,(gensym) ,(cadr m))
  814.             `(,(gensym) ,@(cadr m)))
  815.             `(gclisp:MACRO ,@(cadr m))))
  816.           new-entries))
  817.     (if (eq :compiler-menv (car env))
  818.     `(:compiler-menv ,@new-entries ,@(cdr env))
  819.       (append new-entries env))))
  820.  
  821. (defun environment-function (env fn)
  822.   (let ((entry (lisp::lexical-function fn env)))
  823.     (and entry 
  824.      (eq entry 'lisp::lexical-function)
  825.      fn)))
  826.  
  827. (defun environment-macro (env macro)
  828.   (let ((entry (assoc macro (if (eq :compiler-menv (first env))
  829.                  (rest env)
  830.                    env))))
  831.     (and entry
  832.      (consp entry)
  833.      (symbolp (car entry))            ;name
  834.      (symbolp (cadr entry))            ;gcl:macro or gensym
  835.      (nthcdr 2 entry))))
  836.  
  837. );#+gclisp
  838.  
  839.  
  840. ;;;; CMU Common Lisp version of environment frobbing stuff.
  841.  
  842. ;;; In CMU Common Lisp, the environment is represented with a structure
  843. ;;; that holds alists for the functional things, variables, blocks, etc.
  844. ;;; Only the c::lexenv-functions slot is relevent.  It holds:
  845. ;;; Alist (name . what), where What is either a Functional (a local function)
  846. ;;; or a list (MACRO . <function>) (a local macro, with the specifier
  847. ;;; expander.)    Note that Name may be a (SETF <name>) function.
  848.  
  849. #+:CMU
  850. (progn
  851.  
  852. (defmacro with-augmented-environment
  853.       ((new-env old-env &key functions macros) &body body)
  854.   `(let ((,new-env (with-augmented-environment-internal ,old-env
  855.                             ,functions
  856.                             ,macros)))
  857.      ,@body))
  858.  
  859. (defun with-augmented-environment-internal (env functions macros)
  860.   ;; Note: In order to record the correct function definition, we would
  861.   ;; have to create an interpreted closure, but the with-new-definition
  862.   ;; macro down below makes no distinction between flet and labels, so
  863.   ;; we have no idea what to use for the environment.  So we just blow it
  864.   ;; off, 'cause anything real we do would be wrong.  We still have to
  865.   ;; make an entry so we can tell functions from macros.
  866.   (let ((env (or env (c::make-null-environment))))
  867.     (c::make-lexenv 
  868.       :default env
  869.       :functions
  870.       (append (mapcar #'(lambda (f)
  871.               (cons (car f) (c::make-functional :lexenv env)))
  872.               functions)
  873.           (mapcar #'(lambda (m)
  874.               (list* (car m) 'c::macro
  875.                  (coerce (cadr m) 'function)))
  876.               macros)))))
  877.  
  878. (defun environment-function (env fn)
  879.   (when env
  880.     (let ((entry (assoc fn (c::lexenv-functions env) :test #'equal)))
  881.       (and entry
  882.        (c::functional-p (cdr entry))
  883.        (cdr entry)))))
  884.  
  885. (defun environment-macro (env macro)
  886.   (when env
  887.     (let ((entry (assoc macro (c::lexenv-functions env) :test #'eq)))
  888.       (and entry 
  889.        (eq (cadr entry) 'c::macro)
  890.        (function-lambda-expression (cddr entry))))))
  891.  
  892. ); end of #+:CMU
  893.  
  894.  
  895.  
  896. (defmacro with-new-definition-in-environment
  897.       ((new-env old-env macrolet/flet/labels-form) &body body)
  898.   (let ((functions (make-symbol "Functions"))
  899.     (macros (make-symbol "Macros")))
  900.     `(let ((,functions ())
  901.        (,macros ()))
  902.        (ecase (car ,macrolet/flet/labels-form)
  903.      ((flet labels)
  904.       (dolist (fn (cadr ,macrolet/flet/labels-form))
  905.         (push fn ,functions)))
  906.      ((macrolet)
  907.       (dolist (mac (cadr ,macrolet/flet/labels-form))
  908.         (push (list (car mac)
  909.             (convert-macro-to-lambda (cadr mac)
  910.                          (cddr mac)
  911.                          (string (car mac))))
  912.           ,macros))))
  913.        (with-augmented-environment
  914.           (,new-env ,old-env :functions ,functions :macros ,macros)
  915.      ,@body))))
  916.  
  917. #-Genera
  918. (defun convert-macro-to-lambda (llist body &optional (name "Dummy Macro"))
  919.   (let ((gensym (make-symbol name)))
  920.     (eval `(defmacro ,gensym ,llist ,@body))
  921.     (macro-function gensym)))
  922.  
  923. #+Genera
  924. (defun convert-macro-to-lambda (llist body &optional (name "Dummy Macro"))
  925.   (si:defmacro-1
  926.     'sys:named-lambda 'sys:special (make-symbol name) llist body))
  927.  
  928.  
  929.  
  930.  
  931.  
  932. ;;;
  933. ;;; Now comes the real walker.
  934. ;;;
  935. ;;; As the walker walks over the code, it communicates information to itself
  936. ;;; about the walk.  This information includes the walk function, variable
  937. ;;; bindings, declarations in effect etc.  This information is inherently
  938. ;;; lexical, so the walker passes it around in the actual environment the
  939. ;;; walker passes to macroexpansion functions.  This is what makes the
  940. ;;; nested-walk-form facility work properly.
  941. ;;;
  942. (defmacro walker-environment-bind ((var env &rest key-args)
  943.                       &body body)
  944.   `(with-augmented-environment
  945.      (,var ,env :macros (walker-environment-bind-1 ,env ,.key-args))
  946.      .,body))
  947.  
  948. (defvar *key-to-walker-environment* (gensym))
  949.  
  950. (defun env-lock (env)
  951.   (environment-macro env *key-to-walker-environment*))
  952.  
  953. (defun walker-environment-bind-1 (env &key (walk-function nil wfnp)
  954.                        (walk-form nil wfop)
  955.                        (declarations nil decp)
  956.                        (lexical-variables nil lexp))
  957.   (let ((lock (environment-macro env *key-to-walker-environment*)))
  958.     (list
  959.       (list *key-to-walker-environment*
  960.         (list (if wfnp walk-function     (car lock))
  961.           (if wfop walk-form         (cadr lock))
  962.           (if decp declarations      (caddr lock))
  963.           (if lexp lexical-variables (cadddr lock)))))))
  964.           
  965. (defun env-walk-function (env)
  966.   (car (env-lock env)))
  967.  
  968. (defun env-walk-form (env)
  969.   (cadr (env-lock env)))
  970.  
  971. (defun env-declarations (env)
  972.   (caddr (env-lock env)))
  973.  
  974. (defun env-lexical-variables (env)
  975.   (cadddr (env-lock env)))
  976.  
  977.  
  978. (defun note-declaration (declaration env)
  979.   (push declaration (caddr (env-lock env))))
  980.  
  981. (defun note-lexical-binding (thing env)
  982.   (push (list thing :lexical-var) (cadddr (env-lock env))))
  983.  
  984.  
  985. (defun VARIABLE-LEXICAL-P (var env)
  986.   (let ((entry (member var (env-lexical-variables env) :key #'car)))
  987.     (when (eq (cadar entry) :lexical-var)
  988.       entry)))
  989.  
  990. (defun variable-symbol-macro-p (var env)
  991.   (let ((entry (member var (env-lexical-variables env) :key #'car)))
  992.     (when (eq (cadar entry) :macro)
  993.       entry)))
  994.  
  995.  
  996. (defvar *VARIABLE-DECLARATIONS* '(special))
  997.  
  998. (defun VARIABLE-DECLARATION (declaration var env)
  999.   (if (not (member declaration *variable-declarations*))
  1000.       (error "~S is not a recognized variable declaration." declaration)
  1001.       (let ((id (or (variable-lexical-p var env) var)))
  1002.     (dolist (decl (env-declarations env))
  1003.       (when (and (eq (car decl) declaration)
  1004.              (eq (cadr decl) id))
  1005.         (return decl))))))
  1006.  
  1007. (defun VARIABLE-SPECIAL-P (var env)
  1008.   (or (not (null (variable-declaration 'special var env)))
  1009.       (variable-globally-special-p var)))
  1010.  
  1011. ;;;
  1012. ;;; VARIABLE-GLOBALLY-SPECIAL-P is used to ask if a variable has been
  1013. ;;; declared globally special.  Any particular CommonLisp implementation
  1014. ;;; should customize this function accordingly and send their customization
  1015. ;;; back.
  1016. ;;;
  1017. ;;; The default version of variable-globally-special-p is probably pretty
  1018. ;;; slow, so it uses *globally-special-variables* as a cache to remember
  1019. ;;; variables that it has already figured out are globally special.
  1020. ;;;
  1021. ;;; This would need to be reworked if an unspecial declaration got added to
  1022. ;;; Common Lisp.
  1023. ;;;
  1024. ;;; Common Lisp nit:
  1025. ;;;   variable-globally-special-p should be defined in Common Lisp.
  1026. ;;;
  1027. #-(or Genera Cloe-Runtime Lucid Xerox Excl KCL IBCL (and dec vax common) :CMU HP-HPLabs
  1028.       GCLisp TI pyramid)
  1029. (defvar *globally-special-variables* ())
  1030.  
  1031. (defun variable-globally-special-p (symbol)
  1032.   #+Genera                      (si:special-variable-p symbol)
  1033.   #+Cloe-Runtime        (compiler::specialp symbol)
  1034.   #+Lucid                       (lucid::proclaimed-special-p symbol)
  1035.   #+TI                          (get symbol 'special)
  1036.   #+Xerox                       (il:variable-globally-special-p symbol)
  1037.   #+(and dec vax common)        (get symbol 'system::globally-special)
  1038.   #+(or KCL IBCL)               (si:specialp symbol)
  1039.   #+excl                        (get symbol 'excl::.globally-special.)
  1040.   #+:CMU            (eq (ext:info variable kind symbol) :special)
  1041.   #+HP-HPLabs                   (member (get symbol 'impl:vartype)
  1042.                     '(impl:fluid impl:global)
  1043.                     :test #'eq)
  1044.   #+:GCLISP                     (gclisp::special-p symbol)
  1045.   #+pyramid            (or (get symbol 'lisp::globally-special)
  1046.                     (get symbol
  1047.                      'clc::globally-special-in-compiler))
  1048.   #+:CORAL                      (ccl::proclaimed-special-p symbol)
  1049.   #-(or Genera Cloe-Runtime Lucid Xerox Excl KCL IBCL (and dec vax common) :CMU HP-HPLabs
  1050.     GCLisp TI pyramid :CORAL)
  1051.   (or (not (null (member symbol *globally-special-variables* :test #'eq)))
  1052.       (when (eval `(flet ((ref () ,symbol))
  1053.              (let ((,symbol '#,(list nil)))
  1054.                (and (boundp ',symbol) (eq ,symbol (ref))))))
  1055.     (push symbol *globally-special-variables*)
  1056.     t)))
  1057.  
  1058.  
  1059.   ;;   
  1060. ;;;;;; Handling of special forms (the infamous 24).
  1061.   ;;
  1062. ;;;
  1063. ;;; and I quote...
  1064. ;;; 
  1065. ;;;     The set of special forms is purposely kept very small because
  1066. ;;;     any program analyzing program (read code walker) must have
  1067. ;;;     special knowledge about every type of special form. Such a
  1068. ;;;     program needs no special knowledge about macros...
  1069. ;;;
  1070. ;;; So all we have to do here is a define a way to store and retrieve
  1071. ;;; templates which describe how to walk the 24 special forms and we are all
  1072. ;;; set...
  1073. ;;;
  1074. ;;; Well, its a nice concept, and I have to admit to being naive enough that
  1075. ;;; I believed it for a while, but not everyone takes having only 24 special
  1076. ;;; forms as seriously as might be nice.  There are (at least) 3 ways to
  1077. ;;; lose:
  1078. ;;
  1079. ;;;   1 - Implementation x implements a Common Lisp special form as a macro
  1080. ;;;       which expands into a special form which:
  1081. ;;;         - Is a common lisp special form (not likely)
  1082. ;;;         - Is not a common lisp special form (on the 3600 IF --> COND).
  1083. ;;;
  1084. ;;;     * We can safe ourselves from this case (second subcase really) by
  1085. ;;;       checking to see if there is a template defined for something
  1086. ;;;       before we check to see if we we can macroexpand it.
  1087. ;;;
  1088. ;;;   2 - Implementation x implements a Common Lisp macro as a special form.
  1089. ;;;
  1090. ;;;     * This is a screw, but not so bad, we save ourselves from it by
  1091. ;;;       defining extra templates for the macros which are *likely* to
  1092. ;;;       be implemented as special forms.  (DO, DO* ...)
  1093. ;;;
  1094. ;;;   3 - Implementation x has a special form which is not on the list of
  1095. ;;;       Common Lisp special forms.
  1096. ;;;
  1097. ;;;     * This is a bad sort of a screw and happens more than I would like
  1098. ;;;       to think, especially in the implementations which provide more
  1099. ;;;       than just Common Lisp (3600, Xerox etc.).
  1100. ;;;       The fix is not terribly staisfactory, but will have to do for
  1101. ;;;       now.  There is a hook in get walker-template which can get a
  1102. ;;;       template from the implementation's own walker.  That template
  1103. ;;;       has to be converted, and so it may be that the right way to do
  1104. ;;;       this would actually be for that implementation to provide an
  1105. ;;;       interface to its walker which looks like the interface to this
  1106. ;;;       walker.
  1107. ;;;
  1108.  
  1109. (eval-when (compile load eval)
  1110.  
  1111. (defmacro get-walker-template-internal (x) ;Has to be inside eval-when because
  1112.   `(get ,x 'walker-template))           ;Golden Common Lisp doesn't hack
  1113.                        ;compile time definition of macros
  1114.                        ;right for setf.
  1115.  
  1116. (defmacro define-walker-template
  1117.       (name &optional (template '(nil repeat (eval))))
  1118.   `(eval-when (load eval)
  1119.      (setf (get-walker-template-internal ',name) ',template)))
  1120. )
  1121.  
  1122. (defun get-walker-template (x)
  1123.   (cond ((symbolp x)
  1124.      (or (get-walker-template-internal x)
  1125.          (get-implementation-dependent-walker-template x)))
  1126.     ((and (listp x) (eq (car x) 'lambda))
  1127.      '(lambda repeat (eval)))
  1128.     (t
  1129.      (error "Can't get template for ~S" x))))
  1130.  
  1131. (defun get-implementation-dependent-walker-template (x)
  1132.   (declare (ignore x))
  1133.   ())
  1134.  
  1135.  
  1136.   ;;   
  1137. ;;;;;; The actual templates
  1138.   ;;   
  1139.  
  1140. (define-walker-template BLOCK                (NIL NIL REPEAT (EVAL)))
  1141. (define-walker-template CATCH                (NIL EVAL REPEAT (EVAL)))
  1142. (define-walker-template COMPILER-LET         walk-compiler-let)
  1143. (define-walker-template DECLARE              walk-unexpected-declare)
  1144. (define-walker-template EVAL-WHEN            (NIL QUOTE REPEAT (EVAL)))
  1145. (define-walker-template FLET                 walk-flet)
  1146. (define-walker-template FUNCTION             (NIL CALL))
  1147. (define-walker-template GO                   (NIL QUOTE))
  1148. (define-walker-template IF                   walk-if)
  1149. (define-walker-template LABELS               walk-labels)
  1150. (define-walker-template LAMBDA               walk-lambda)
  1151. (define-walker-template LET                  walk-let)
  1152. (define-walker-template LET*                 walk-let*)
  1153. (define-walker-template LOCALLY              walk-locally)
  1154. (define-walker-template MACROLET             walk-macrolet)
  1155. (define-walker-template MULTIPLE-VALUE-CALL  (NIL EVAL REPEAT (EVAL)))
  1156. (define-walker-template MULTIPLE-VALUE-PROG1 (NIL RETURN REPEAT (EVAL)))
  1157. (define-walker-template MULTIPLE-VALUE-SETQ  walk-multiple-value-setq)
  1158. (define-walker-template MULTIPLE-VALUE-BIND  walk-multiple-value-bind)
  1159. (define-walker-template PROGN                (NIL REPEAT (EVAL)))
  1160. (define-walker-template PROGV                (NIL EVAL EVAL REPEAT (EVAL)))
  1161. (define-walker-template QUOTE                (NIL QUOTE))
  1162. (define-walker-template RETURN-FROM          (NIL QUOTE REPEAT (RETURN)))
  1163. (define-walker-template SETQ                 walk-setq)
  1164. (define-walker-template SYMBOL-MACROLET      walk-symbol-macrolet)
  1165. (define-walker-template TAGBODY              walk-tagbody)
  1166. (define-walker-template THE                  (NIL QUOTE EVAL))
  1167. #+cmu(define-walker-template EXT:TRULY-THE   (NIL QUOTE EVAL))
  1168. (define-walker-template THROW                (NIL EVAL EVAL))
  1169. (define-walker-template UNWIND-PROTECT       (NIL RETURN REPEAT (EVAL)))
  1170.  
  1171. ;;; The new special form.
  1172. ;(define-walker-template pcl::LOAD-TIME-EVAL       (NIL EVAL))
  1173.  
  1174. ;;;
  1175. ;;; And the extra templates...
  1176. ;;;
  1177. (define-walker-template DO      walk-do)
  1178. (define-walker-template DO*     walk-do*)
  1179. (define-walker-template PROG    walk-prog)
  1180. (define-walker-template PROG*   walk-prog*)
  1181. (define-walker-template COND    (NIL REPEAT ((TEST REPEAT (EVAL)))))
  1182.  
  1183. #+Genera
  1184. (progn
  1185.   (define-walker-template zl::named-lambda walk-named-lambda)
  1186.   (define-walker-template SCL:LETF walk-let)
  1187.   (define-walker-template SCL:LETF* walk-let*)
  1188.   )
  1189.  
  1190. #+Lucid
  1191. (progn
  1192.   (define-walker-template #+LCL3.0 lucid-common-lisp:named-lambda
  1193.               #-LCL3.0 sys:named-lambda walk-named-lambda)
  1194.   )
  1195.  
  1196. #+(or KCL IBCL)
  1197. (progn
  1198.   (define-walker-template lambda-block walk-named-lambda);Not really right,
  1199.                              ;we don't hack block
  1200.                                  ;names anyways.
  1201.   )
  1202.  
  1203. #+TI
  1204. (progn
  1205.   (define-walker-template TICL::LET-IF walk-let-if)
  1206.   )
  1207.  
  1208. #+:Coral
  1209. (progn
  1210.   (define-walker-template ccl:%stack-block walk-let)
  1211.   )
  1212.  
  1213.  
  1214.  
  1215. (defvar walk-form-expand-macros-p nil)
  1216.  
  1217. (defun macroexpand-all (form &optional environment)
  1218.   (let ((walk-form-expand-macros-p t))
  1219.     (walk-form form environment)))
  1220.  
  1221. (defun WALK-FORM (form
  1222.           &optional environment
  1223.                 (walk-function
  1224.                   #'(lambda (subform context env)
  1225.                   (declare (ignore context env))
  1226.                   subform)))
  1227.   (walker-environment-bind (new-env environment :walk-function walk-function)
  1228.     (walk-form-internal form :eval new-env)))
  1229.  
  1230. ;;;
  1231. ;;; nested-walk-form provides an interface that allows nested macros, each
  1232. ;;; of which must walk their body to just do one walk of the body of the
  1233. ;;; inner macro.  That inner walk is done with a walk function which is the
  1234. ;;; composition of the two walk functions.
  1235. ;;;
  1236. ;;; This facility works by having the walker annotate the environment that
  1237. ;;; it passes to macroexpand-1 to know which form is being macroexpanded.
  1238. ;;; If then the &whole argument to the macroexpansion function is eq to
  1239. ;;; the env-walk-form of the environment, nested-walk-form can be certain
  1240. ;;; that there are no intervening layers and that a nested walk is alright.
  1241. ;;;
  1242. ;;; There are some semantic problems with this facility.  In particular, if
  1243. ;;; the outer walk function returns T as its walk-no-more-p value, this will
  1244. ;;; prevent the inner walk function from getting a chance to walk the subforms
  1245. ;;; of the form.  This is almost never what you want, since it destroys the
  1246. ;;; equivalence between this nested-walk-form function and two seperate
  1247. ;;; walk-forms.
  1248. ;;;
  1249. (defun NESTED-WALK-FORM (whole
  1250.              form
  1251.              &optional environment
  1252.                    (walk-function
  1253.                      #'(lambda (subform context env)
  1254.                      (declare (ignore context env))
  1255.                      subform)))
  1256.   (if (eq whole (env-walk-form environment))
  1257.       (let ((outer-walk-function (env-walk-function environment)))
  1258.     (throw whole
  1259.       (walk-form
  1260.         form
  1261.         environment
  1262.         #'(lambda (f c e)
  1263.         ;; First loop to make sure the inner walk function
  1264.         ;; has done all it wants to do with this form.
  1265.         ;; Basically, what we are doing here is providing
  1266.         ;; the same contract walk-form-internal normally
  1267.         ;; provides to the inner walk function.
  1268.         (let ((inner-result nil)
  1269.               (inner-no-more-p nil)
  1270.               (outer-result nil)
  1271.               (outer-no-more-p nil))
  1272.           (loop
  1273.             (multiple-value-setq (inner-result inner-no-more-p)
  1274.                      (funcall walk-function f c e))
  1275.             (cond (inner-no-more-p (return))
  1276.               ((not (eq inner-result f)))
  1277.               ((not (consp inner-result)) (return))
  1278.               ((get-walker-template (car inner-result)) (return))
  1279.               (t
  1280.                (multiple-value-bind (expansion macrop)
  1281.                    (walker-environment-bind
  1282.                      (new-env e :walk-form inner-result)
  1283.                  (macroexpand-1 inner-result new-env))
  1284.                  (if macrop
  1285.                  (setq inner-result expansion)
  1286.                  (return)))))
  1287.             (setq f inner-result))
  1288.           (multiple-value-setq (outer-result outer-no-more-p)
  1289.                        (funcall outer-walk-function
  1290.                         inner-result
  1291.                         c
  1292.                         e))
  1293.           (values outer-result
  1294.               (and inner-no-more-p outer-no-more-p)))))))
  1295.       (walk-form form environment walk-function)))
  1296.  
  1297. ;;;
  1298. ;;; WALK-FORM-INTERNAL is the main driving function for the code walker. It
  1299. ;;; takes a form and the current context and walks the form calling itself or
  1300. ;;; the appropriate template recursively.
  1301. ;;;
  1302. ;;;   "It is recommended that a program-analyzing-program process a form
  1303. ;;;    that is a list whose car is a symbol as follows:
  1304. ;;;
  1305. ;;;     1. If the program has particular knowledge about the symbol,
  1306. ;;;        process the form using special-purpose code.  All of the
  1307. ;;;        standard special forms should fall into this category.
  1308. ;;;     2. Otherwise, if macro-function is true of the symbol apply
  1309. ;;;        either macroexpand or macroexpand-1 and start over.
  1310. ;;;     3. Otherwise, assume it is a function call. "
  1311. ;;;     
  1312.  
  1313. (defun walk-form-internal (form context env)
  1314.   ;; First apply the walk-function to perform whatever translation
  1315.   ;; the user wants to this form.  If the second value returned
  1316.   ;; by walk-function is T then we don't recurse...
  1317.   (catch form
  1318.     (multiple-value-bind (newform walk-no-more-p)
  1319.       (funcall (env-walk-function env) form context env)
  1320.       (catch newform
  1321.     (cond
  1322.      (walk-no-more-p newform)
  1323.      ((not (eq form newform))
  1324.       (walk-form-internal newform context env))
  1325.      ((not (consp newform))
  1326.       (let ((symmac (car (variable-symbol-macro-p newform env))))
  1327.         (if symmac
  1328.         (let ((newnewform (walk-form-internal (cddr symmac)
  1329.                               context env)))
  1330.           (if (eq newnewform (cddr symmac))
  1331.               (if walk-form-expand-macros-p newnewform newform)
  1332.               newnewform))
  1333.         newform)))
  1334.      (t
  1335.       (let* ((fn (car newform))
  1336.          (template (get-walker-template fn)))
  1337.         (if template
  1338.         (if (symbolp template)
  1339.             (funcall template newform context env)
  1340.             (walk-template newform template context env))
  1341.         (multiple-value-bind
  1342.             (newnewform macrop)
  1343.             (walker-environment-bind
  1344.             (new-env env :walk-form newform)
  1345.               (macroexpand-1 newform new-env))
  1346.           (cond
  1347.            (macrop
  1348.             (let ((newnewnewform (walk-form-internal newnewform context
  1349.                                  env)))
  1350.               (if (eq newnewnewform newnewform)
  1351.               (if walk-form-expand-macros-p newnewform newform)
  1352.               newnewnewform)))
  1353.            ((and (symbolp fn)
  1354.              (not (fboundp fn))
  1355.              (special-form-p fn))
  1356.             (error
  1357.              "~S is a special form, not defined in the CommonLisp.~%~
  1358.               manual This code walker doesn't know how to walk it.~%~
  1359.               Define a template for this special form and try again."
  1360.              fn))
  1361.            (t
  1362.             ;; Otherwise, walk the form as if its just a standard 
  1363.             ;; functioncall using a template for standard function
  1364.             ;; call.
  1365.             (walk-template
  1366.              newnewform '(call repeat (eval)) context env))))))))))))
  1367.  
  1368. (defun walk-template (form template context env)
  1369.   (if (atom template)
  1370.       (ecase template
  1371.         ((EVAL FUNCTION TEST EFFECT RETURN)
  1372.          (walk-form-internal form :EVAL env))
  1373.         ((QUOTE NIL) form)
  1374.         (SET
  1375.           (walk-form-internal form :SET env))
  1376.         ((LAMBDA CALL)
  1377.      (cond ((or (symbolp form)
  1378.             (and (listp form)
  1379.              (= (length form) 2)
  1380.              (eq (car form) 'setf)))
  1381.         form)
  1382.            #+Lispm
  1383.            ((sys:validate-function-spec form) form)
  1384.            (t (walk-form-internal form context env)))))
  1385.       (case (car template)
  1386.         (REPEAT
  1387.           (walk-template-handle-repeat form
  1388.                                        (cdr template)
  1389.                        ;; For the case where nothing happens
  1390.                        ;; after the repeat optimize out the
  1391.                        ;; call to length.
  1392.                        (if (null (cddr template))
  1393.                        ()
  1394.                        (nthcdr (- (length form)
  1395.                               (length
  1396.                             (cddr template)))
  1397.                            form))
  1398.                                        context
  1399.                        env))
  1400.         (IF
  1401.       (walk-template form
  1402.              (if (if (listp (cadr template))
  1403.                  (eval (cadr template))
  1404.                  (funcall (cadr template) form))
  1405.                  (caddr template)
  1406.                  (cadddr template))
  1407.              context
  1408.              env))
  1409.         (REMOTE
  1410.           (walk-template form (cadr template) context env))
  1411.         (otherwise
  1412.           (cond ((atom form) form)
  1413.                 (t (recons form
  1414.                            (walk-template
  1415.                  (car form) (car template) context env)
  1416.                            (walk-template
  1417.                  (cdr form) (cdr template) context env))))))))
  1418.  
  1419. (defun walk-template-handle-repeat (form template stop-form context env)
  1420.   (if (eq form stop-form)
  1421.       (walk-template form (cdr template) context env)
  1422.       (walk-template-handle-repeat-1 form
  1423.                      template
  1424.                      (car template)
  1425.                      stop-form
  1426.                      context
  1427.                      env)))
  1428.  
  1429. (defun walk-template-handle-repeat-1 (form template repeat-template
  1430.                        stop-form context env)
  1431.   (cond ((null form) ())
  1432.         ((eq form stop-form)
  1433.          (if (null repeat-template)
  1434.              (walk-template stop-form (cdr template) context env)       
  1435.              (error "While handling repeat:
  1436.                      ~%~Ran into stop while still in repeat template.")))
  1437.         ((null repeat-template)
  1438.          (walk-template-handle-repeat-1
  1439.        form template (car template) stop-form context env))
  1440.         (t
  1441.          (recons form
  1442.                  (walk-template (car form) (car repeat-template) context env)
  1443.                  (walk-template-handle-repeat-1 (cdr form)
  1444.                         template
  1445.                         (cdr repeat-template)
  1446.                         stop-form
  1447.                         context
  1448.                         env)))))
  1449.  
  1450. (defun walk-repeat-eval (form env)
  1451.   (and form
  1452.        (recons form
  1453.            (walk-form-internal (car form) :eval env)
  1454.            (walk-repeat-eval (cdr form) env))))
  1455.  
  1456. (defun recons (x car cdr)
  1457.   (if (or (not (eq (car x) car))
  1458.           (not (eq (cdr x) cdr)))
  1459.       (cons car cdr)
  1460.       x))
  1461.  
  1462. (defun relist (x &rest args)
  1463.   (if (null args)
  1464.       nil
  1465.       (relist-internal x args nil)))
  1466.  
  1467. (defun relist* (x &rest args)
  1468.   (relist-internal x args 't))
  1469.  
  1470. (defun relist-internal (x args *p)
  1471.   (if (null (cdr args))
  1472.       (if *p
  1473.       (car args)
  1474.       (recons x (car args) nil))
  1475.       (recons x
  1476.           (car args)
  1477.           (relist-internal (cdr x) (cdr args) *p))))
  1478.  
  1479.  
  1480.   ;;   
  1481. ;;;;;; Special walkers
  1482.   ;;
  1483.  
  1484. (defun walk-declarations (body fn env
  1485.                    &optional doc-string-p declarations old-body
  1486.                    &aux (form (car body)) macrop new-form)
  1487.   (cond ((and (stringp form)            ;might be a doc string
  1488.               (cdr body)            ;isn't the returned value
  1489.               (null doc-string-p)        ;no doc string yet
  1490.               (null declarations))        ;no declarations yet
  1491.          (recons body
  1492.                  form
  1493.                  (walk-declarations (cdr body) fn env t)))
  1494.         ((and (listp form) (eq (car form) 'declare))
  1495.          ;; Got ourselves a real live declaration.  Record it, look for more.
  1496.          (dolist (declaration (cdr form))
  1497.        (let ((type (car declaration))
  1498.          (name (cadr declaration))
  1499.          (args (cddr declaration)))
  1500.          (if (member type *variable-declarations*)
  1501.          (note-declaration `(,type
  1502.                      ,(or (variable-lexical-p name env) name)
  1503.                      ,.args)
  1504.                    env)
  1505.          (note-declaration declaration env))
  1506.          (push declaration declarations)))
  1507.          (recons body
  1508.                  form
  1509.                  (walk-declarations
  1510.            (cdr body) fn env doc-string-p declarations)))
  1511.         ((and form
  1512.           (listp form)
  1513.           (null (get-walker-template (car form)))
  1514.           (progn
  1515.         (multiple-value-setq (new-form macrop)
  1516.                      (macroexpand-1 form env))
  1517.         macrop))
  1518.      ;; This form was a call to a macro.  Maybe it expanded
  1519.      ;; into a declare?  Recurse to find out.
  1520.      (walk-declarations (recons body new-form (cdr body))
  1521.                 fn env doc-string-p declarations
  1522.                 (or old-body body)))
  1523.     (t
  1524.      ;; Now that we have walked and recorded the declarations,
  1525.      ;; call the function our caller provided to expand the body.
  1526.      ;; We call that function rather than passing the real-body
  1527.      ;; back, because we are RECONSING up the new body.
  1528.      (funcall fn (or old-body body) env))))
  1529.  
  1530.  
  1531. (defun walk-unexpected-declare (form context env)
  1532.   (declare (ignore context env))
  1533.   (warn "Encountered declare ~S in a place where a declare was not expected."
  1534.     form)
  1535.   form)
  1536.  
  1537. (defun walk-arglist (arglist context env &optional (destructuringp nil)
  1538.                      &aux arg)
  1539.   (cond ((null arglist) ())
  1540.         ((symbolp (setq arg (car arglist)))
  1541.          (or (member arg lambda-list-keywords)
  1542.              (note-lexical-binding arg env))
  1543.          (recons arglist
  1544.                  arg
  1545.                  (walk-arglist (cdr arglist)
  1546.                                context
  1547.                    env
  1548.                                (and destructuringp
  1549.                     (not (member arg
  1550.                          lambda-list-keywords))))))
  1551.         ((consp arg)
  1552.          (prog1 (recons arglist
  1553.             (if destructuringp
  1554.                 (walk-arglist arg context env destructuringp)
  1555.                 (relist* arg
  1556.                      (car arg)
  1557.                      (walk-form-internal (cadr arg) :eval env)
  1558.                      (cddr arg)))
  1559.             (walk-arglist (cdr arglist) context env nil))
  1560.                 (if (symbolp (car arg))
  1561.                     (note-lexical-binding (car arg) env)
  1562.                     (note-lexical-binding (cadar arg) env))
  1563.                 (or (null (cddr arg))
  1564.                     (not (symbolp (caddr arg)))
  1565.                     (note-lexical-binding (caddr arg) env))))
  1566.           (t
  1567.        (error "Can't understand something in the arglist ~S" arglist))))
  1568.  
  1569. (defun walk-let (form context env)
  1570.   (walk-let/let* form context env nil))
  1571.  
  1572. (defun walk-let* (form context env)
  1573.   (walk-let/let* form context env t))
  1574.  
  1575. (defun walk-prog (form context env)
  1576.   (walk-prog/prog* form context env nil))
  1577.  
  1578. (defun walk-prog* (form context env)
  1579.   (walk-prog/prog* form context env t))
  1580.  
  1581. (defun walk-do (form context env)
  1582.   (walk-do/do* form context env nil))
  1583.  
  1584. (defun walk-do* (form context env)
  1585.   (walk-do/do* form context env t))
  1586.  
  1587. (defun walk-let/let* (form context old-env sequentialp)
  1588.   (walker-environment-bind (new-env old-env)
  1589.     (let* ((let/let* (car form))
  1590.        (bindings (cadr form))
  1591.        (body (cddr form))
  1592.        (walked-bindings 
  1593.          (walk-bindings-1 bindings
  1594.                   old-env
  1595.                   new-env
  1596.                   context
  1597.                   sequentialp))
  1598.        (walked-body
  1599.          (walk-declarations body #'walk-repeat-eval new-env)))
  1600.       (relist*
  1601.     form let/let* walked-bindings walked-body))))
  1602.  
  1603. (defun walk-locally (form context env)
  1604.   (declare (ignore context))
  1605.   (let* ((locally (car form))
  1606.      (body (cdr form))
  1607.      (walked-body
  1608.       (walk-declarations body #'walk-repeat-eval env)))
  1609.     (relist*
  1610.      form locally walked-body)))
  1611.  
  1612. (defun walk-prog/prog* (form context old-env sequentialp)
  1613.   (walker-environment-bind (new-env old-env)
  1614.     (let* ((possible-block-name (second form))
  1615.        (blocked-prog (and (symbolp possible-block-name)
  1616.                   (not (eq possible-block-name 'nil)))))
  1617.       (multiple-value-bind (let/let* block-name bindings body)
  1618.       (if blocked-prog
  1619.           (values (car form) (cadr form) (caddr form) (cdddr form))
  1620.           (values (car form) nil         (cadr  form) (cddr  form)))
  1621.     (let* ((walked-bindings 
  1622.          (walk-bindings-1 bindings
  1623.                   old-env
  1624.                   new-env
  1625.                   context
  1626.                   sequentialp))
  1627.            (walked-body
  1628.          (walk-declarations 
  1629.            body
  1630.            #'(lambda (real-body real-env)
  1631.                (walk-tagbody-1 real-body context real-env))
  1632.            new-env)))
  1633.       (if block-name
  1634.           (relist*
  1635.         form let/let* block-name walked-bindings walked-body)
  1636.           (relist*
  1637.         form let/let* walked-bindings walked-body)))))))
  1638.  
  1639. (defun walk-do/do* (form context old-env sequentialp)
  1640.   (walker-environment-bind (new-env old-env)
  1641.     (let* ((do/do* (car form))
  1642.        (bindings (cadr form))
  1643.        (end-test (caddr form))
  1644.        (body (cdddr form))
  1645.        (walked-bindings (walk-bindings-1 bindings
  1646.                          old-env
  1647.                          new-env
  1648.                          context
  1649.                          sequentialp))
  1650.        (walked-body
  1651.          (walk-declarations body #'walk-repeat-eval new-env)))
  1652.       (relist* form
  1653.            do/do*
  1654.            (walk-bindings-2 bindings walked-bindings context new-env)
  1655.            (walk-template end-test '(test repeat (eval)) context new-env)
  1656.            walked-body))))
  1657.  
  1658. (defun walk-let-if (form context env)
  1659.   (let ((test (cadr form))
  1660.     (bindings (caddr form))
  1661.     (body (cdddr form)))
  1662.     (walk-form-internal
  1663.       `(let ()
  1664.      (declare (special ,@(mapcar #'(lambda (x) (if (listp x) (car x) x))
  1665.                      bindings)))
  1666.      (flet ((.let-if-dummy. () ,@body))
  1667.        (if ,test
  1668.            (let ,bindings (.let-if-dummy.))
  1669.            (.let-if-dummy.))))
  1670.       context
  1671.       env)))
  1672.  
  1673. (defun walk-multiple-value-setq (form context env)
  1674.   (let ((vars (cadr form)))
  1675.     (if (some #'(lambda (var)
  1676.           (variable-symbol-macro-p var env))
  1677.           vars)
  1678.     (let* ((temps (mapcar #'(lambda (var) (declare (ignore var)) (gensym)) vars))
  1679.            (sets (mapcar #'(lambda (var temp) `(setq ,var ,temp)) vars temps))
  1680.            (expanded `(multiple-value-bind ,temps 
  1681.                    ,(caddr form)
  1682.                  ,@sets))
  1683.            (walked (walk-form-internal expanded context env)))
  1684.       (if (eq walked expanded)
  1685.           form
  1686.           walked))
  1687.     (walk-template form '(nil (repeat (set)) eval) context env))))
  1688.  
  1689. (defun walk-multiple-value-bind (form context old-env)
  1690.   (walker-environment-bind (new-env old-env)
  1691.     (let* ((mvb (car form))
  1692.        (bindings (cadr form))
  1693.        (mv-form (walk-template (caddr form) 'eval context old-env))
  1694.        (body (cdddr form))
  1695.        walked-bindings
  1696.        (walked-body
  1697.          (walk-declarations 
  1698.            body
  1699.            #'(lambda (real-body real-env)
  1700.            (setq walked-bindings
  1701.              (walk-bindings-1 bindings
  1702.                       old-env
  1703.                       new-env
  1704.                       context
  1705.                       nil))
  1706.            (walk-repeat-eval real-body real-env))
  1707.            new-env)))
  1708.       (relist* form mvb walked-bindings mv-form walked-body))))
  1709.  
  1710. (defun walk-bindings-1 (bindings old-env new-env context sequentialp)
  1711.   (and bindings
  1712.        (let ((binding (car bindings)))
  1713.          (recons bindings
  1714.                  (if (symbolp binding)
  1715.                      (prog1 binding
  1716.                             (note-lexical-binding binding new-env))
  1717.                      (prog1 (relist* binding
  1718.                      (car binding)
  1719.                      (walk-form-internal (cadr binding)
  1720.                              context
  1721.                              (if sequentialp
  1722.                                  new-env
  1723.                                  old-env))
  1724.                      (cddr binding))    ;save cddr for DO/DO*
  1725.                                 ;it is the next value
  1726.                                 ;form. Don't walk it
  1727.                                 ;now though.
  1728.                             (note-lexical-binding (car binding) new-env)))
  1729.                  (walk-bindings-1 (cdr bindings)
  1730.                   old-env
  1731.                   new-env
  1732.                   context
  1733.                   sequentialp)))))
  1734.  
  1735. (defun walk-bindings-2 (bindings walked-bindings context env)
  1736.   (and bindings
  1737.        (let ((binding (car bindings))
  1738.              (walked-binding (car walked-bindings)))
  1739.          (recons bindings
  1740.          (if (symbolp binding)
  1741.              binding
  1742.              (relist* binding
  1743.                   (car walked-binding)
  1744.                   (cadr walked-binding)
  1745.                   (walk-template (cddr binding)
  1746.                          '(eval)
  1747.                          context
  1748.                          env)))         
  1749.                  (walk-bindings-2 (cdr bindings)
  1750.                   (cdr walked-bindings)
  1751.                   context
  1752.                   env)))))
  1753.  
  1754. (defun walk-lambda (form context old-env)
  1755.   (walker-environment-bind (new-env old-env)
  1756.     (let* ((arglist (cadr form))
  1757.            (body (cddr form))
  1758.            (walked-arglist (walk-arglist arglist context new-env))
  1759.            (walked-body
  1760.              (walk-declarations body #'walk-repeat-eval new-env)))
  1761.       (relist* form
  1762.                (car form)
  1763.            walked-arglist
  1764.                walked-body))))
  1765.  
  1766. (defun walk-named-lambda (form context old-env)
  1767.   (walker-environment-bind (new-env old-env)
  1768.     (let* ((name (cadr form))
  1769.        (arglist (caddr form))
  1770.            (body (cdddr form))
  1771.            (walked-arglist (walk-arglist arglist context new-env))
  1772.            (walked-body
  1773.              (walk-declarations body #'walk-repeat-eval new-env)))
  1774.       (relist* form
  1775.                (car form)
  1776.            name
  1777.            walked-arglist
  1778.                walked-body))))  
  1779.  
  1780. (defun walk-setq (form context env)
  1781.   (if (cdddr form)
  1782.       (let* ((expanded (let ((rforms nil)
  1783.                  (tail (cdr form)))
  1784.              (loop (when (null tail) (return (nreverse rforms)))
  1785.                    (let ((var (pop tail)) (val (pop tail)))
  1786.                  (push `(setq ,var ,val) rforms)))))
  1787.          (walked (walk-repeat-eval expanded env)))
  1788.     (if (eq expanded walked)
  1789.         form
  1790.         `(progn ,@walked)))
  1791.       (let* ((var (cadr form))
  1792.          (val (caddr form))
  1793.          (symmac (car (variable-symbol-macro-p var env))))
  1794.     (if symmac
  1795.         (let* ((expanded `(setf ,(cddr symmac) ,val))
  1796.            (walked (walk-form-internal expanded context env)))
  1797.           (if (eq expanded walked)
  1798.           form
  1799.           walked))
  1800.         (relist form 'setq
  1801.             (walk-form-internal var :set env)
  1802.             (walk-form-internal val :eval env))))))
  1803.  
  1804. (defun walk-symbol-macrolet (form context old-env)
  1805.   (declare (ignore context))
  1806.   (let* ((bindings (cadr form)))
  1807.     (walker-environment-bind
  1808.     (new-env old-env
  1809.          :lexical-variables
  1810.          (append (mapcar #'(lambda (binding)
  1811.                      `(,(car binding)
  1812.                        :macro . ,(cadr binding)))
  1813.                  bindings)
  1814.              (env-lexical-variables old-env)))
  1815.       (relist* form 'symbol-macrolet bindings
  1816.            (walk-repeat-eval (cddr form) new-env)))))
  1817.  
  1818. (defun walk-tagbody (form context env)
  1819.   (recons form (car form) (walk-tagbody-1 (cdr form) context env)))
  1820.  
  1821. (defun walk-tagbody-1 (form context env)
  1822.   (and form
  1823.        (recons form
  1824.                (walk-form-internal (car form)
  1825.                    (if (symbolp (car form)) 'quote context)
  1826.                    env)
  1827.                (walk-tagbody-1 (cdr form) context env))))
  1828.  
  1829. (defun walk-compiler-let (form context old-env)
  1830.   (declare (ignore context))
  1831.   (let ((vars ())
  1832.     (vals ()))
  1833.     (dolist (binding (cadr form))
  1834.       (cond ((symbolp binding) (push binding vars) (push nil vals))
  1835.         (t
  1836.          (push (car binding) vars)
  1837.          (push (eval (cadr binding)) vals))))
  1838.     (relist* form
  1839.          (car form)
  1840.          (cadr form)
  1841.          (progv vars vals (walk-repeat-eval (cddr form) old-env)))))
  1842.  
  1843. (defun walk-macrolet (form context old-env)
  1844.   (walker-environment-bind (macro-env
  1845.                 nil
  1846.                 :walk-function (env-walk-function old-env))
  1847.     (labels ((walk-definitions (definitions)
  1848.            (and definitions
  1849.             (let ((definition (car definitions)))
  1850.               (recons definitions
  1851.                               (relist* definition
  1852.                                        (car definition)
  1853.                                        (walk-arglist (cadr definition)
  1854.                              context
  1855.                              macro-env
  1856.                              t)
  1857.                                        (walk-declarations (cddr definition)
  1858.                               #'walk-repeat-eval
  1859.                               macro-env))
  1860.                   (walk-definitions (cdr definitions)))))))
  1861.       (with-new-definition-in-environment (new-env old-env form)
  1862.     (relist* form
  1863.          (car form)
  1864.          (walk-definitions (cadr form))
  1865.          (walk-declarations (cddr form)
  1866.                     #'walk-repeat-eval
  1867.                     new-env))))))
  1868.  
  1869. (defun walk-flet (form context old-env)
  1870.   (labels ((walk-definitions (definitions)
  1871.          (if (null definitions)
  1872.          ()
  1873.          (recons definitions
  1874.              (walk-lambda (car definitions) context old-env)
  1875.              (walk-definitions (cdr definitions))))))
  1876.     (recons form
  1877.         (car form)
  1878.         (recons (cdr form)
  1879.             (walk-definitions (cadr form))
  1880.             (with-new-definition-in-environment (new-env old-env form)
  1881.               (walk-declarations (cddr form)
  1882.                      #'walk-repeat-eval
  1883.                      new-env))))))
  1884.  
  1885. (defun walk-labels (form context old-env)
  1886.   (with-new-definition-in-environment (new-env old-env form)
  1887.     (labels ((walk-definitions (definitions)
  1888.            (if (null definitions)
  1889.            ()
  1890.            (recons definitions
  1891.                (walk-lambda (car definitions) context new-env)
  1892.                (walk-definitions (cdr definitions))))))
  1893.       (recons form
  1894.           (car form)
  1895.           (recons (cdr form)
  1896.               (walk-definitions (cadr form))
  1897.               (walk-declarations (cddr form)
  1898.                      #'walk-repeat-eval
  1899.                      new-env))))))
  1900.  
  1901. (defun walk-if (form context env)
  1902.   (let ((predicate (cadr form))
  1903.     (arm1 (caddr form))
  1904.     (arm2 
  1905.       (if (cddddr form)
  1906.           (progn
  1907.         (warn "In the form:~%~S~%~
  1908.                        IF only accepts three arguments, you are using ~D.~%~
  1909.                        It is true that some Common Lisps support this, but ~
  1910.                        it is not~%~
  1911.                        truly legal Common Lisp.  For now, this code ~
  1912.                        walker is interpreting ~%~
  1913.                        the extra arguments as extra else clauses. ~
  1914.                        Even if this is what~%~
  1915.                        you intended, you should fix your source code."
  1916.               form
  1917.               (length (cdr form)))
  1918.         (cons 'progn (cdddr form)))
  1919.           (cadddr form))))
  1920.     (relist form
  1921.         'if
  1922.         (walk-form-internal predicate context env)
  1923.         (walk-form-internal arm1 context env)
  1924.         (walk-form-internal arm2 context env))))
  1925.  
  1926.  
  1927. ;;;
  1928. ;;; Tests tests tests
  1929. ;;;
  1930.  
  1931. #|
  1932. ;;; 
  1933. ;;; Here are some examples of the kinds of things you should be able to do
  1934. ;;; with your implementation of the macroexpansion environment hacking
  1935. ;;; mechanism.
  1936. ;;; 
  1937. ;;; with-lexical-macros is kind of like macrolet, but it only takes names
  1938. ;;; of the macros and actual macroexpansion functions to use to macroexpand
  1939. ;;; them.  The win about that is that for macros which want to wrap several
  1940. ;;; macrolets around their body, they can do this but have the macroexpansion
  1941. ;;; functions be compiled.  See the WITH-RPUSH example.
  1942. ;;;
  1943. ;;; If the implementation had a special way of communicating the augmented
  1944. ;;; environment back to the evaluator that would be totally great.  It would
  1945. ;;; mean that we could just augment the environment then pass control back
  1946. ;;; to the implementations own compiler or interpreter.  We wouldn't have
  1947. ;;; to call the actual walker.  That would make this much faster.  Since the
  1948. ;;; principal client of this is defmethod it would make compiling defmethods
  1949. ;;; faster and that would certainly be a win.
  1950. ;;;
  1951. (defmacro with-lexical-macros (macros &body body &environment old-env)
  1952.   (with-augmented-environment (new-env old-env :macros macros)
  1953.     (walk-form (cons 'progn body) :environment new-env)))
  1954.  
  1955. (defun expand-rpush (form env)
  1956.   `(push ,(caddr form) ,(cadr form)))
  1957.  
  1958. (defmacro with-rpush (&body body)
  1959.   `(with-lexical-macros ,(list (list 'rpush #'expand-rpush)) ,@body))
  1960.  
  1961.  
  1962. ;;;
  1963. ;;; Unfortunately, I don't have an automatic tester for the walker.  
  1964. ;;; Instead there is this set of test cases with a description of
  1965. ;;; how each one should go.
  1966. ;;; 
  1967. (defmacro take-it-out-for-a-test-walk (form)
  1968.   `(take-it-out-for-a-test-walk-1 ',form))
  1969.  
  1970. (defun take-it-out-for-a-test-walk-1 (form)
  1971.   (terpri)
  1972.   (terpri)
  1973.   (let ((copy-of-form (copy-tree form))
  1974.     (result (walk-form form nil
  1975.           #'(lambda (x y env)
  1976.               (format t "~&Form: ~S ~3T Context: ~A" x y)
  1977.               (when (symbolp x)
  1978.             (let ((lexical (variable-lexical-p x env))
  1979.                   (special (variable-special-p x env)))
  1980.               (when lexical
  1981.                 (format t ";~3T")
  1982.                 (format t "lexically bound"))
  1983.               (when special
  1984.                 (format t ";~3T")
  1985.                 (format t "declared special"))
  1986.               (when (boundp x)
  1987.                 (format t ";~3T")
  1988.                 (format t "bound: ~S " (eval x)))))
  1989.               x))))
  1990.     (cond ((not (equal result copy-of-form))
  1991.        (format t "~%Warning: Result not EQUAL to copy of start."))
  1992.       ((not (eq result form))
  1993.        (format t "~%Warning: Result not EQ to copy of start.")))
  1994.     (pprint result)
  1995.     result))
  1996.  
  1997. (defmacro foo (&rest ignore) ''global-foo)
  1998.  
  1999. (defmacro bar (&rest ignore) ''global-bar)
  2000.  
  2001. (take-it-out-for-a-test-walk (list arg1 arg2 arg3))
  2002. (take-it-out-for-a-test-walk (list (cons 1 2) (list 3 4 5)))
  2003.  
  2004. (take-it-out-for-a-test-walk (progn (foo) (bar 1)))
  2005.  
  2006. (take-it-out-for-a-test-walk (block block-name a b c))
  2007. (take-it-out-for-a-test-walk (block block-name (list a) b c))
  2008.  
  2009. (take-it-out-for-a-test-walk (catch catch-tag (list a) b c))
  2010. ;;;
  2011. ;;; This is a fairly simple macrolet case.  While walking the body of the
  2012. ;;; macro, x should be lexically bound. In the body of the macrolet form
  2013. ;;; itself, x should not be bound.
  2014. ;;; 
  2015. (take-it-out-for-a-test-walk
  2016.   (macrolet ((foo (x) (list x) ''inner))
  2017.     x
  2018.     (foo 1)))
  2019.  
  2020. ;;;
  2021. ;;; A slightly more complex macrolet case.  In the body of the macro x
  2022. ;;; should not be lexically bound.  In the body of the macrolet form itself
  2023. ;;; x should be bound.  Note that THIS CASE WILL CAUSE AN ERROR when it
  2024. ;;; tries to macroexpand the call to foo.
  2025. ;;; 
  2026. (take-it-out-for-a-test-walk
  2027.      (let ((x 1))
  2028.        (macrolet ((foo () (list x) ''inner))
  2029.      x
  2030.      (foo))))
  2031.  
  2032. ;;;
  2033. ;;; A truly hairy use of compiler-let and macrolet.  In the body of the
  2034. ;;; macro x should not be lexically bound.  In the body of the macrolet
  2035. ;;; itself x should not be lexically bound.  But the macro should expand
  2036. ;;; into 1.
  2037. ;;; 
  2038. (take-it-out-for-a-test-walk
  2039.   (compiler-let ((x 1))
  2040.     (let ((x 2))
  2041.       (macrolet ((foo () x))
  2042.     x
  2043.     (foo)))))
  2044.  
  2045.  
  2046. (take-it-out-for-a-test-walk
  2047.   (flet ((foo (x) (list x y))
  2048.      (bar (x) (list x y)))
  2049.     (foo 1)))
  2050.  
  2051. (take-it-out-for-a-test-walk
  2052.   (let ((y 2))
  2053.     (flet ((foo (x) (list x y))
  2054.        (bar (x) (list x y)))
  2055.       (foo 1))))
  2056.  
  2057. (take-it-out-for-a-test-walk
  2058.   (labels ((foo (x) (bar x))
  2059.        (bar (x) (foo x)))
  2060.     (foo 1)))
  2061.  
  2062. (take-it-out-for-a-test-walk
  2063.   (flet ((foo (x) (foo x)))
  2064.     (foo 1)))
  2065.  
  2066. (take-it-out-for-a-test-walk
  2067.   (flet ((foo (x) (foo x)))
  2068.     (flet ((bar (x) (foo x)))
  2069.       (bar 1))))
  2070.  
  2071. (take-it-out-for-a-test-walk (compiler-let ((a 1) (b 2)) (foo a) b))
  2072. (take-it-out-for-a-test-walk (prog () (declare (special a b))))
  2073. (take-it-out-for-a-test-walk (let (a b c)
  2074.                                (declare (special a b))
  2075.                                (foo a) b c))
  2076. (take-it-out-for-a-test-walk (let (a b c)
  2077.                                (declare (special a) (special b))
  2078.                                (foo a) b c))
  2079. (take-it-out-for-a-test-walk (let (a b c)
  2080.                                (declare (special a))
  2081.                                (declare (special b))
  2082.                                (foo a) b c))
  2083. (take-it-out-for-a-test-walk (let (a b c)
  2084.                                (declare (special a))
  2085.                                (declare (special b))
  2086.                                (let ((a 1))
  2087.                                  (foo a) b c)))
  2088. (take-it-out-for-a-test-walk (eval-when ()
  2089.                                a
  2090.                                (foo a)))
  2091. (take-it-out-for-a-test-walk (eval-when (eval when load)
  2092.                                a
  2093.                                (foo a)))
  2094.  
  2095. (take-it-out-for-a-test-walk (multiple-value-bind (a b) (foo a b) (list a b)))
  2096. (take-it-out-for-a-test-walk (multiple-value-bind (a b)
  2097.                  (foo a b)
  2098.                    (declare (special a))
  2099.                    (list a b)))
  2100. (take-it-out-for-a-test-walk (progn (function foo)))
  2101. (take-it-out-for-a-test-walk (progn a b (go a)))
  2102. (take-it-out-for-a-test-walk (if a b c))
  2103. (take-it-out-for-a-test-walk (if a b))
  2104. (take-it-out-for-a-test-walk ((lambda (a b) (list a b)) 1 2))
  2105. (take-it-out-for-a-test-walk ((lambda (a b) (declare (special a)) (list a b))
  2106.                   1 2))
  2107. (take-it-out-for-a-test-walk (let ((a a) (b a) (c b)) (list a b c)))
  2108. (take-it-out-for-a-test-walk (let* ((a a) (b a) (c b)) (list a b c)))
  2109. (take-it-out-for-a-test-walk (let ((a a) (b a) (c b))
  2110.                                (declare (special a b))
  2111.                                (list a b c)))
  2112. (take-it-out-for-a-test-walk (let* ((a a) (b a) (c b))
  2113.                                (declare (special a b))
  2114.                                (list a b c)))
  2115. (take-it-out-for-a-test-walk (let ((a 1) (b 2))
  2116.                                (foo bar)
  2117.                                (declare (special a))
  2118.                                (foo a b)))
  2119. (take-it-out-for-a-test-walk (multiple-value-call #'foo a b c))
  2120. (take-it-out-for-a-test-walk (multiple-value-prog1 a b c))
  2121. (take-it-out-for-a-test-walk (progn a b c))
  2122. (take-it-out-for-a-test-walk (progv vars vals a b c))
  2123. (take-it-out-for-a-test-walk (quote a))
  2124. (take-it-out-for-a-test-walk (return-from block-name a b c))
  2125. (take-it-out-for-a-test-walk (setq a 1))
  2126. (take-it-out-for-a-test-walk (setq a (foo 1) b (bar 2) c 3))
  2127. (take-it-out-for-a-test-walk (tagbody a b c (go a)))
  2128. (take-it-out-for-a-test-walk (the foo (foo-form a b c)))
  2129. (take-it-out-for-a-test-walk (throw tag-form a))
  2130. (take-it-out-for-a-test-walk (unwind-protect (foo a b) d e f))
  2131.  
  2132. (defmacro flet-1 (a b) ''outer)
  2133. (defmacro labels-1 (a b) ''outer)
  2134.  
  2135. (take-it-out-for-a-test-walk
  2136.   (flet ((flet-1 (a b) () (flet-1 a b) (list a b)))
  2137.     (flet-1 1 2)
  2138.     (foo 1 2)))
  2139. (take-it-out-for-a-test-walk
  2140.   (labels ((label-1 (a b) () (label-1 a b)(list a b)))
  2141.     (label-1 1 2)
  2142.     (foo 1 2)))
  2143. (take-it-out-for-a-test-walk (macrolet ((macrolet-1 (a b) (list a b)))
  2144.                                (macrolet-1 a b)
  2145.                                (foo 1 2)))
  2146.  
  2147. (take-it-out-for-a-test-walk (macrolet ((foo (a) `(inner-foo-expanded ,a)))
  2148.                                (foo 1)))
  2149.  
  2150. (take-it-out-for-a-test-walk (progn (bar 1)
  2151.                                     (macrolet ((bar (a)
  2152.                          `(inner-bar-expanded ,a)))
  2153.                                       (bar 2))))
  2154.  
  2155. (take-it-out-for-a-test-walk (progn (bar 1)
  2156.                                     (macrolet ((bar (s)
  2157.                          (bar s)
  2158.                          `(inner-bar-expanded ,s)))
  2159.                                       (bar 2))))
  2160.  
  2161. (take-it-out-for-a-test-walk (cond (a b)
  2162.                                    ((foo bar) a (foo a))))
  2163.  
  2164.  
  2165. (let ((the-lexical-variables ()))
  2166.   (walk-form '(let ((a 1) (b 2))
  2167.         #'(lambda (x) (list a b x y)))
  2168.          ()
  2169.          #'(lambda (form context env)
  2170.          (when (and (symbolp form)
  2171.                 (variable-lexical-p form env))
  2172.            (push form the-lexical-variables))
  2173.          form))
  2174.   (or (and (= (length the-lexical-variables) 3)
  2175.        (member 'a the-lexical-variables)
  2176.        (member 'b the-lexical-variables)
  2177.        (member 'x the-lexical-variables))
  2178.       (error "Walker didn't do lexical variables of a closure properly.")))
  2179.     
  2180. |#
  2181.  
  2182. ()
  2183.  
  2184.